﻿using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;

namespace DataAccess.SqlServer
{
    /// <summary>
    /// Work for sqlserver
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SqlAccess<T> : DataAccessAbstract<T> where T : new()
    {
        public SqlAccess(string connStr)
            : base(connStr, new SqlEntityConverter<T>())
        {

        }

        /// <see cref="IDataAccess.QueryEntitys"/>
        public override List<T> QueryEntitys(string procStr, DbParam[] dbParams)
        {
            List<T> list = new List<T>();

            using (SqlConnection conn = new SqlConnection(this.connStr))
            using (SqlCommand command = new SqlCommand(procStr, conn))
            {
                conn.Open();
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.AddRange(ConvertParams(dbParams));
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        T obj = converter.Convert(reader);
                        list.Add(obj);
                    }
                }

                SetOutputValue(dbParams);
            }

            return list;
        }

        /// <see cref="IDataAccess.FindEntity"/>
        public override T FindEntity(string procStr, DbParam[] dbParams)
        {
            List<T> entitys = QueryEntitys(procStr, dbParams);

            return entitys.Count == 0 ? default(T) : entitys[0];
        }

        /// <see cref="IDataAccess.ExecProc"/>
        public override void ExecProc(string procStr, DbParam[] dbParams)
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            using (SqlCommand command = new SqlCommand(procStr, conn))
            {
                conn.Open();
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.AddRange(ConvertParams(dbParams));
                command.ExecuteNonQuery();

                SetOutputValue(dbParams);
            }
        }

        /// <see cref="DataAccessAbstract.ConvertParams"/>
        protected override DbParameter[] ConvertParams(DbParam[] dbParams)
        {
            List<SqlParameter> sqlP = new List<SqlParameter>();

            foreach (DbParam p in dbParams)
            {
                p.DbParameter = new SqlParameter(p.ParamName, p.ParamValue);
                p.DbParameter.Direction = p.Direction;
                sqlP.Add(p.DbParameter as SqlParameter);
            }

            return sqlP.ToArray();
        }
    }
}
